import math

from pyecharts import options as opts


class Repo:
    def __init__(self, context, initCash):
        self.lastKeepPos = 0
        self.contxt = context  # 上下文，用于获取最新价格
        self.initCash = initCash  # 初始资金
        self.currentAsset = initCash  # 当前总资产
        self.leftCash = self.initCash  # 剩余现金
        self.keepNum = 0  # 持有股数
        self.closePrice = 0  # 成本价


    def buyByRate(self, pos, index):
        """按比例交易"""
        if pos < self.lastKeepPos:
            return
        pos = round(pos, 2)
        pos = pos - self.lastKeepPos
        newPrice = self.contxt.getNewPrice(index)
        num = int(pos * self.currentAsset / newPrice)
        if num * newPrice > self.leftCash:
            num = int(self.leftCash / newPrice)
        self.buy(num, index)

    def sellByRate(self, pos, index):
        """按比例交易"""
        pos = round(pos, 2)
        num = self.keepNum
        if pos < self.lastKeepPos:
            num = int(self.getKeepNum() * pos)



        self.sell(num, index)

    def buy(self, num, index):
        """"
        买入操作
        """
        if num <= 0:
            print("买入数量不能小于0")
            return
        # 检查剩余资金是否够用
        newPrice = self.contxt.getNewPrice(index)
        if newPrice * num > self.leftCash:
            print(f'资金不足 left.cash = {self.leftCash}, newPrice = {newPrice}, num = {num}')
            return
        # 成本价计算
        if self.keepNum == 0:
            self.closePrice = newPrice
        else:
            newClose = (self.closePrice * self.keepNum + num * newPrice) / (self.keepNum + num)
            self.closePrice = newClose
            assert self.closePrice > 0
        self.keepNum += num
        self.leftCash = self.leftCash - num * newPrice
        self.lastKeepPos = round(self.keepNum * newPrice / self.currentAsset, 2)
        if self.closePrice == 0:
            print("出错")
            return
        print(f"买入 {num} * {newPrice} "
              f"self.currentAsset={self.currentAsset}"
              f" keepos={self.lastKeepPos} keep={self.keepNum} left={self.leftCash} close={self.closePrice}")

        self.mark('买', newPrice, "#0000ff", index)

    def sell(self, num, index):
        """"卖出操作"""
        if num <= 0:
            print("持仓不足， 或不支持卖空")
            return
        newPrice = self.contxt.getNewPrice(index)
        if self.keepNum < num:
            return
        print(f"卖出 {num} * {newPrice}")
        if self.keepNum == num:
            # 清仓
            self.leftCash = self.leftCash + num * newPrice
            self.currentAsset = self.leftCash
            profitCash = (newPrice - self.closePrice) * num
            print(f'本次盈利：{profitCash} close={self.closePrice} price={newPrice}')
            self.closePrice = 0
            self.keepNum = 0
        else:
            # 减仓
            profitCash = (newPrice - self.closePrice) * self.keepNum
            self.closePrice = newPrice - (profitCash / (self.keepNum - num))
            self.keepNum -= num
            self.leftCash += profitCash + num * newPrice

        self.lastKeepPos = round(self.keepNum * newPrice / self.currentAsset, 2)
        print(f"卖出 {num} * {newPrice} "
              f"self.currentAsset={self.currentAsset}"
              f" keepos={self.lastKeepPos} keep={self.keepNum} left={self.leftCash} close={self.closePrice} profit={self.getTotalProfitRate(index)}")
        self.mark('卖', newPrice, "#ff0000", index)

    def getTotalProfitRate(self, index):
        """"获取总收益率"""
        newPrice = self.contxt.getNewPrice(index)
        self.currentAsset = self.keepNum * newPrice + self.leftCash
        # 计算总资产
        return (self.currentAsset - self.initCash) / self.initCash * 100

    def getCurrentProfitRate(self, index):
        """计算当前盈利"""
        if self.keepNum <= 0:
            return 0
        newPrice = self.contxt.getNewPrice(index)

        return (newPrice - self.closePrice) / self.closePrice

    def getKeepNum(self):
        return self.keepNum
    def getKeepPos(self):
        ## 返回当前持仓比例
        return self.lastKeepPos

    def mark(self, name, value, color, index):
        ma = {'name': name, 'value': value, "color": color, 'index': index}
        self.contxt.mark(ma)
